package cn.nzcong.jpress.addon.articlesync.platform;

import cn.nzcong.jpress.addon.articlesync.common.Constant;
import cn.nzcong.jpress.addon.articlesync.common.Exception.AuthException;
import cn.nzcong.jpress.addon.articlesync.common.Exception.ExternalServiceException;
import cn.nzcong.jpress.addon.articlesync.common.util.HttpUtil;
import cn.nzcong.jpress.addon.articlesync.enums.PlatformEnum;
import cn.nzcong.jpress.addon.articlesync.vo.PlatformVerifyVo;
import cn.nzcong.jpress.addon.articlesync.vo.config.ToutiaoConfig;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * 简书平台
 *
 * @author zecong.nian
 */
public class PlatformTouTiao extends BasePlatform<ToutiaoConfig> {

    @Override
    public PlatformEnum getPlatformEnum() {
        return PlatformEnum.TOU_TIAO;
    }

    @Override
    public PlatformVerifyVo doVerify(ToutiaoConfig config) {
        boolean isValid = true;
        String reason = "";
        String userId = "";
        String nickname = "";
        try{
            if(config == null){
                throw new AuthException("账号配置为空");
            } else if(!config.isEnable()){
                throw new AuthException("配置未开启");
            }
            Long mediaId = config.getMediaId();
            if(mediaId == null){
                throw new AuthException("头条号ID未设置");
            }
            if(StringUtils.isBlank(config.getCookie())){
                throw new AuthException("cookie未设置");
            }
            JSONObject respObj = this.getMediaId(config);
            Long cookieMediaId = respObj.getLong("media_id");
            if(!mediaId.equals(cookieMediaId)){
                throw new AuthException("cookie对应头条号为：%s", String.valueOf(cookieMediaId));
            }
            userId = String.valueOf(cookieMediaId);
            nickname = respObj.getString("name");
        } catch (AuthException e){
            isValid = false;
            reason = e.getMessage();
        }
        return PlatformVerifyVo.builder()
                .enable(config.isEnable())
                .isValid(isValid)
                .reason(reason)
                .platformName(getPlatformEnum().getName())
                .platformDisplayName(getPlatformEnum().getDisplayName())
                .userId(userId)
                .nickname(nickname)
                .build();
    }

    @Override
    protected void _doPublishArticle(String title, String article, String author, String tags, String categories) {
        Long pgcId = this.getOldArticle(title);
        try {
            pgcId = this.publish(pgcId, title, article, false);
        } catch (UnsupportedEncodingException e) {
            throw new ExternalServiceException(e, "存草稿失败");
        }
        if(Boolean.TRUE.equals(super.getConfigObj().isDraftOnly())){
            return;
        }
        try {
            this.checkTitle(pgcId, title);
            this.publish(pgcId, title, article, true);
        } catch (UnsupportedEncodingException e) {
            throw new ExternalServiceException(e, "发布失败");
        }
    }

    @Override
    protected String _doUploadImg(String imgLocalUrl) {
        try {
            String resp = HttpUtil.uploadImage("https://mp.toutiao.com/tools/upload_picture/?type=ueditor&pgc_watermark=1&action=uploadimage&encode=utf-8",
                    "upfile",imgLocalUrl, new HashMap<String, String>(){{
                        put("cookie", "sessionid=ed121046b2ebf808bffb16ea376e629f;");
                    }});
            // 失效cookie返回主页html
            if(!resp.startsWith("{")){
                throw new ExternalServiceException("返回非json，可能是cookie失效");
            }
            JSONObject respObj = JSONObject.parseObject(resp);
            String state = respObj.getString("state");
            if(!"success".equalsIgnoreCase(state)){
                //{  "state": "上传失败",   "reason": "\u53c2\u6570upfile\u9519\u8bef\uff0c\u8bf7\u91cd\u65b0\u4e0a\u4f20"}
                throw new ExternalServiceException(respObj.getString("reason"));
            }
            return respObj.getString("url");
        } catch (Exception e) {
            throw new ExternalServiceException(e, "图片上传失败", e.getMessage());
        }
    }

    private Map<String, String> toHttpHeader(ToutiaoConfig config){
        return new HashMap<String, String>(){{
            put("cookie", config.getCookie());
        }};
    }

    private Map<String, String> getHttpHeader(){
        return this.toHttpHeader(super.getConfigObj());
    }

    private enum ArticleStatusEnum{
        UNKNOWN(0, "未知"),
        DRAFT(1, "草稿"),
        PUBLISHED(3, "已发表"),
        CHECKING(5, "审核中"),
        ;
        int status;
        String name;
        ArticleStatusEnum(int stauts, String name){
            this.status = stauts;
            this.name = name;
        }

        public static ArticleStatusEnum valueOf(Integer status){
            if(status == null){
                return UNKNOWN;
            }
            for(ArticleStatusEnum val : ArticleStatusEnum.values()){
                if(val.status == status){
                    return val;
                }
            }
            return UNKNOWN;
        }
    }


    private JSONObject getMediaId(ToutiaoConfig config){
        String respStr = HttpUtil.httpGet("https://mp.toutiao.com/user_login_status_api/",
                Collections.EMPTY_MAP, this.toHttpHeader(config));
        try {
            JSONObject respObj = JSONObject.parseObject(respStr);
            JSONObject media_info = respObj.getJSONObject("reason").getJSONObject("media").getJSONObject("media_info");
            if(media_info == null || media_info.isEmpty()){
                throw new ExternalServiceException("TOUTIAO verify: media_info is Emmpty - %s", respStr);
            }
            return media_info;
        } catch (Exception e){
            throw new AuthException("账号失效：cookie已失效");
        }
    }

    // 找旧文章，每页最多20条，最多查找10页，同名文章并且审核通过报错
    private Long getOldArticle(String title){
        Long pgcId = null;
        for(int i = 0 ; pgcId == null && i < 10 ; i++){
            int page = i + 1;
            String respStr = HttpUtil.httpGet("https://mp.toutiao.com/mp/agw/article/list", new HashMap<String, Object>(){{
                put("size", 20);
//            put("status", "draft");
                put("page", page);
            }}, getHttpHeader());
            JSONObject resp = JSONObject.parseObject(respStr);
            if(0 != resp.getIntValue("code") || resp.getJSONObject("data") == null || resp.getJSONObject("data").isEmpty()){
                throw new ExternalServiceException(resp.getString("message"));
            }
            List<JSONObject> items = resp.getJSONObject("data").getJSONArray("content").toJavaList(JSONObject.class);
            if(items == null){
                return null;
            }
            for(JSONObject item : items){
                if(!title.equalsIgnoreCase(item.getString("title"))){
                    continue;
                }
                ArticleStatusEnum status = ArticleStatusEnum.valueOf(item.getInteger("status"));
                // 以下状态不允许修改
                if(Arrays.asList(ArticleStatusEnum.UNKNOWN,// 状态异常
                        ArticleStatusEnum.PUBLISHED,    // 已发布
                        ArticleStatusEnum.CHECKING)     // 审核中
                        .contains(status)){
                    throw new AuthException("存在同名文章，状态：%s", status.name);
                }
                pgcId = item.getLongValue("pgc_id");
                break;
            }
        }
        return pgcId;
    }

    private Long publish(Long pgcId, String title, String contant, boolean isPublish) throws UnsupportedEncodingException {
        Long mediaId = super.getConfigObj().getMediaId();
        Calendar timerTime = Calendar.getInstance();
        timerTime.add(Calendar.HOUR, 12);
        String respStr = HttpUtil.doFormPost("https://mp.toutiao.com/mp/agw/article/publish?source=mp&type=article", new HashMap<String, String>(){{
            put("article_type", "0");
            if (pgcId != null) {
                put("pgc_id", String.valueOf(pgcId));
            } else {
                put("title_id", System.currentTimeMillis() + "_" + mediaId);
            }
            put("article_type", "0");
            put("source", "0");
            put("title", URLEncoder.encode(title, Constant.CHARSET_UTF8));
            put("content", URLEncoder.encode(contant, Constant.CHARSET_UTF8));
            put("pgc_feed_covers", URLEncoder.encode("[]", Constant.CHARSET_UTF8));
            put("claim_origin", "0");
            put("origin_debut_check_pgc_normal", "0");
            put("qy_self_recommendation", "0");
            put("is_fans_article", "0");
            put("govern_forward", "0");
            put("praise", "0");
            put("disable_praise", "0");
            put("tree_plan_article", "0");
            put("article_ad_type", "3");
            put("activity_tag", "0");
            put("community_sync", "0");
            put("save", isPublish ? "1" : "0");
            put("timer_status", "0");
            put("timer_time", DateFormatUtils.format(timerTime.getTimeInMillis(), Constant.DATE_FORMAT_MINUTE));
        }}, this.getHttpHeader());

        JSONObject resp = JSONObject.parseObject(respStr);
        if(0 != resp.getIntValue("code") || resp.getJSONObject("data") == null || resp.getJSONObject("data").isEmpty()){
            throw new ExternalServiceException(resp.getString("message"));
        }
        return resp.getJSONObject("data").getLong("pgc_id");
    }


    public void checkTitle(Long pgcId, String title) throws UnsupportedEncodingException {
        String respStr = HttpUtil.httpGet("https://mp.toutiao.com/check_title/?title=" + URLEncoder.encode(title, Constant.CHARSET_UTF8) + "&title_id=&item_id=6774042265175196167",
                new HashMap<String, Object>(){{
                    put("title", URLEncoder.encode(title, Constant.CHARSET_UTF8));
                    put("item_id", pgcId);
                }}, this.getHttpHeader());
        JSONObject respObj = JSONObject.parseObject(respStr);
        if(!"success".equalsIgnoreCase(respObj.getString("check_title_msg"))){
            throw new ExternalServiceException(respObj.getString("check_title_msg"));
        }
    }


}
